#!/usr/bin/perl
use warnings;
use strict;
use Net::SSH2;
use Net::Telnet;
use DBI;
use IO::Socket;
# http://cpansearch.perl.org/src/PATL/Time-Out-0.11/README
use Time::Out qw(timeout) ;
use DBI;
use DBD::Oracle;

my $ERROR_NETWORK = "can't connect";
my $ERROR_LOGIN = "can't login";
my $LOGIN_SUCCESSFUL = "login success";
my $IP_ADDRESS;
my $PORT_ADDRESS;
my $remote;
my $dbh;
my $service;
my @accountf;
my @table;
my $account;
my $file_accounts;

sub scan_oracle
{
  my $ORACLE_SID = "XRD";
  my $PASSWORD = $_[3];
  my $USER = $_[2];
  my $TCP_PORT = $_[1];
  $IP_ADDRESS = $_[0];
  $remote = IO::Socket::INET->new(
      PeerAddr => $IP_ADDRESS, 
      PeerPort => $TCP_PORT, # tcp port
      Proto => 'tcp', Timeout => 2);

  if($remote)
  {
    $dbh = DBI->connect("dbi:Oracle:host=$IP_ADDRESS;port=$TCP_PORT;sid=$ORACLE_SID",
	$USER, $PASSWORD);
    if($dbh)
    {
      $dbh->disconnect();
      return $LOGIN_SUCCESSFUL." (".$USER." / ".$PASSWORD.")";
    }
    else
    {
      return $ERROR_LOGIN." (".$USER." / ".$PASSWORD.")";
    }
  }
  else
  {	
    return $ERROR_NETWORK." (".$USER." / ".$PASSWORD.")";
  }
}

sub scan_mounts
{
  $IP_ADDRESS = $_[0];
  my $nb_secs = 3;
  my $command = "";

  timeout $nb_secs => sub 
  {
    $command = `sudo /usr/sbin/showmount -e $IP_ADDRESS`;
  };

  if($@)
  {
    return $ERROR_NETWORK;
  }
  else
  {
    print $command."\n\n";

    if($command =~ /everyone/) 
    {
      return $LOGIN_SUCCESSFUL;
    }

    return $ERROR_LOGIN;
  }
}


sub scan_telnet
{
  $IP_ADDRESS = $_[0];
  my $telnet = Net::Telnet->new(Timeout => 2, Errmode => 'return');
  $telnet->timeout(2);

  if(!$telnet->open($IP_ADDRESS))
  {
    return $ERROR_NETWORK." (".$_[1]." / ".$_[2].")";
  }
  else
  {	
    if(!$telnet->login($_[1], $_[2]))
    {
      return $ERROR_LOGIN." (".$_[1]." / ".$_[2].")";
    }
    else
    {
      return $LOGIN_SUCCESSFUL." (".$_[1]." / ".$_[2].")";
    }
  }

  $telnet->disconnect();
}

sub scan_ssh
{
  $IP_ADDRESS = $_[0];
  my $ssh2 = Net::SSH2->new();
  $ssh2->timeout(100);

  if(!$ssh2->connect($IP_ADDRESS, 22, Timeout=>2))
  {
    return $ERROR_NETWORK." (".$_[1]." / ".$_[2].")";
  }
  else
  {
    if(!$ssh2->auth_password($_[1], $_[2]))
    {
      return $ERROR_LOGIN." (".$_[1]." / ".$_[2].")";
    }
    else
    {
      return $LOGIN_SUCCESSFUL." (".$_[1]." / ".$_[2].")";
    }
  }

  $ssh2->disconnect();
}


sub scan_mysql
{
  $IP_ADDRESS = $_[0];
  $remote = IO::Socket::INET->new(
      PeerAddr => $IP_ADDRESS, 
      PeerPort => 3306, 
      Proto => 'tcp', Timeout => 2);

  if($remote)
  {
    my $dbh = DBI->connect('DBI:mysql:database=information_schema;host='.$IP_ADDRESS, 
	$_[1], $_[2], {PrintError => 0});
    if($dbh)
    {
      $dbh->disconnect();
      return $LOGIN_SUCCESSFUL." (".$_[1]." / ".$_[2].")";
    }
    else
    {
      return $ERROR_LOGIN." (".$_[1]." / ".$_[2].")";
    }
  }
  else
  {	
    return $ERROR_NETWORK." (".$_[1]." / ".$_[2].")";
  }	
}

sub scan_http
{
  $IP_ADDRESS = $_[0];
  $PORT_ADDRESS = $_[1];
  $remote = IO::Socket::INET->new(
      PeerAddr => $IP_ADDRESS, 
      PeerPort => $PORT_ADDRESS, 
      Proto => 'tcp', Timeout => 2);

  if($remote)
  {
    return $ERROR_LOGIN;
  }
  else
  {	
    return $ERROR_NETWORK;
  }	
}

sub scan_udp
{
  $IP_ADDRESS = $_[0];
  $PORT_ADDRESS = $_[1];
  $remote = IO::Socket::INET->new(
      PeerAddr => $IP_ADDRESS, 
      PeerPort => $PORT_ADDRESS, 
      Proto => 'udp', Timeout => 2);

  if($remote)
  {
    return $ERROR_LOGIN;
  }
  else
  {	
    return $ERROR_NETWORK;
  }	
}

if(@ARGV < 4)
{
  print "nombre d'arguments : ".@ARGV."\n";
  print "usage : simplesecuscan.pl ip_address_file result_file services_file accounts_file\n\n";
  exit;
}

open my($file_services), '<', $ARGV[2] or die "can't open ".$ARGV[2];
while($service = <$file_services>)
{
  chomp($service);
  unlink($ARGV[1]."_".$service);
}
close($file_services);

my $i = 0;
open my($file_ips), '<', $ARGV[0] or die "can't open ".$ARGV[0];
while(my $ip = <$file_ips>)
{
  chomp($ip);	
  open my($file_services), '<', $ARGV[2];
  while($service = <$file_services>)
  {
    chomp($service);
    print "$i '$service'\n";
# with login
    if($service eq "ssh" || $service eq "telnet" || $service eq "mysql")
    {		
      open my($file_accounts), '<', $ARGV[3] or die "can't open ".$ARGV[3];
      open my($fileresult), '>>', $ARGV[1]."_".$service;
      my $returnvalue = "start";

      while($account = <$file_accounts>)
      {
	chomp($account);
	@accountf = split(/:/, $account);
	my $nomfonction = "scan_".$service;
	my $subref = \&$nomfonction;
	$returnvalue = &{$subref}($ip, $accountf[0], $accountf[1]);
	print $fileresult $returnvalue." ";
      }

      print $fileresult "\n";
      close($fileresult);
      close($file_accounts);	
    }
# with oracle login
    elsif($service eq "oracle_1521" || $service eq "oracle_1526" || $service eq "oracle_1527" || $service eq "oracle_1529")
    {
      @table = split(/_/, $service);
      open my($file_accounts), '<', $ARGV[3] or die "can't open ".$ARGV[3];
      open my($fileresult), '>>', $ARGV[1]."_".$service;
      my $returnvalue = "start";

      while($account = <$file_accounts>)
      {
	chomp($account);
	@accountf = split(/:/, $account);
	$returnvalue = &scan_oracle($ip, $table[1], $accountf[0], $accountf[1]);
	print $fileresult $returnvalue." ";

      }

      print $fileresult "\n";
      close($fileresult);
      close($file_accounts);	
    }
# without login = just tcp test
    elsif($service eq "citrix_1494" || $service eq "citrix_2598"
	|| $service eq "rdp_3389" || $service eq "rdp_60001" 
	|| $service eq "http_80" || $service eq "http_443" 
	|| $service eq "http_8080" || $service eq "http_389"
	|| $service eq "ftp_21")
    {
      @table = split(/_/,$service);
      open my($fileresult), '>>', $ARGV[1]."_".$service;
      my $returnvalue = &scan_http($ip, $table[1]);
      print $fileresult $returnvalue."\n";;
      close($fileresult);	
    }
# anonymous
    elsif($service eq "mounts")
    {
      open my($fileresult), '>>', $ARGV[1]."_".$service;
      my $returnvalue = &scan_mounts($ip);
      print $fileresult $returnvalue."\n";;
      close($fileresult);
    }
  }
  close($file_services);

  print "$i '$ip'\n";
  $i = $i + 1;
}
close($file_ips);

